﻿using System;
using Cinemachine;
using UnityEngine;
using UnityEngine.Rendering.Universal;
//using Yoozoo.Core.Editor.Utility;
using Yoozoo.Mars.Got;
using ShadowResolution = UnityEngine.Rendering.Universal.ShadowResolution;


namespace Yoozoo.Core.Common
{
    [RequireComponent(typeof(Camera),typeof(UniversalAdditionalCameraData))]
    public class CameraQualityListener : 
        QualityListenerMono<CameraQualityListener.CameraQualitySetting>,
        IRenderPrecisionAdjuster,
        ILightShadowLevelAdjuster,
        ICameraFrustumAdjuster,
        IPcCameraAdjuster
    {
        [Serializable]
        public class CameraQualitySetting : QualitySetting
        {
            public bool renderShadow = true;
            public float shadowDistance = 60.0f;
            public ShadowCascadesOption cascadesOption = ShadowCascadesOption.FourCascades;
            public bool softShadow = true;

            public ShadowResolution shadowResolution = ShadowResolution._1024;
            public bool customRenderScale = false;
            [Range(0.1f,2f)]
            public float renderScale = 1.0f;

            //小米低端机在Low分级下，相机开启PostProcessing但是组件Volume下后效数量为0时会导致画面出现马赛克bug
            //所以增加了一个开关，在完全没有后效的分级下把相机的PostProcessing也给关了
            public bool cameraPostProcessing = true;
            
            public bool colorTexture = false;
            public bool depthTexture = false;
            
            // public bool controllerFrustum = false;
            // public float nearPlaneDistance = 0.01f;
            // public float farPlaneDistance = 1000f;
            // public float fov = 60f;
            
            public void Apply(Camera camera,UniversalAdditionalCameraData addCameraData,CinemachineStateDrivenCamera drivenCamera)
            {
                ApplyShadowQuality(addCameraData);
                ApplyRenderPrecision(addCameraData);

                // if (controllerFrustum)
                // {
                //     if (drivenCamera!=null)
                //     {
                //         foreach (var childCamera in drivenCamera.ChildCameras)
                //         {
                //             CinemachineVirtualCamera child = childCamera as CinemachineVirtualCamera;
                //             if (child)
                //             {
                //                 child.m_Lens.NearClipPlane = nearPlaneDistance;
                //                 child.m_Lens.FarClipPlane = farPlaneDistance;
                //                 child.m_Lens.FieldOfView = fov;
                //             }
                //         }
                //     }
                //     else
                //     {
                //         camera.nearClipPlane = nearPlaneDistance;
                //         camera.farClipPlane = farPlaneDistance;
                //         camera.fieldOfView = fov;
                //     }
                // }
               
            }


            public void ApplyShadowQuality(UniversalAdditionalCameraData addCameraData)
            {
                addCameraData.renderShadows = renderShadow;
                addCameraData.m_ShadowCascades = cascadesOption;
                addCameraData.m_SoftShadowsSupported = softShadow;
                addCameraData.m_mainLightShadowmapResolution = shadowResolution;
                addCameraData.m_ShadowDistance = shadowDistance;
                addCameraData.requiresColorTexture = colorTexture;
                addCameraData.requiresDepthTexture = depthTexture;
                addCameraData.renderPostProcessing = cameraPostProcessing;
                
                Shader.SetGlobalFloat("_ShadowDistance",shadowDistance);
            }
            
            public void ApplyRenderPrecision(UniversalAdditionalCameraData addCameraData)
            {
                addCameraData.m_customRenderScale = customRenderScale;
                addCameraData.m_renderScale = renderScale;
                
                // 如果叠加缩放小于1，那么需要乘以一个比例
                float scaleRatio = QualityHelper.ResolutionQualityListener.scaleRatio;
                scaleRatio = Mathf.Min(1.0f, scaleRatio);
                if ( scaleRatio < 1.0)
                {
                    if (addCameraData.m_customRenderScale)
                    {
                        addCameraData.m_renderScale = renderScale * scaleRatio;
                        Debug.Log($"摄像机：{addCameraData.transform.name} 分辨率设置叠加缩放，实际缩放：{renderScale}， 叠加比例：{scaleRatio}");
                    }
                    else
                    {
                        addCameraData.m_customRenderScale = true;
                        addCameraData.m_renderScale = scaleRatio;
                        Debug.Log($"摄像机：{addCameraData.transform.name} 分辨率设置叠加缩放，叠加比例：{scaleRatio}");
                    }
                }
            }
        }

        public bool renderPrecisionAdjust = true;
        public bool shadowQualityAdjust = true;
        public bool cameraFrustumAdjust = false;
        
        [SerializeField]
        private Camera _camera;
        [SerializeField]
        private UniversalAdditionalCameraData _additionalCamera;
        [SerializeField] 
        private CinemachineStateDrivenCamera _drivenCamera;

        protected override void OnEnable()
        {
            base.OnEnable();
        }

        public override void ChangeQualitySetting(CameraQualitySetting qualitySetting)
        {
            if (_camera == null) _camera = GetComponent<Camera>();
            if (_additionalCamera == null) _additionalCamera = GetComponent<UniversalAdditionalCameraData>();
            qualitySetting.Apply(_camera,_additionalCamera,_drivenCamera);
            //抗锯齿
            if (_additionalCamera.renderPostProcessing)
            {
                if (qualitySetting.Quality > QualityEnum.Medium)
                {
                    _additionalCamera.antialiasing = AntialiasingMode.FastApproximateAntialiasing;
                }
            }
        }
        
        public void ChangeRenderPrecision(QualityEnum quality)
        {
            if(!renderPrecisionAdjust) return;
            CameraQualitySetting qualitySetting = GetQualitySetting(quality);
            if (qualitySetting != null && _additionalCamera != null)
            {
                qualitySetting.ApplyRenderPrecision(_additionalCamera);
            }
            
        }

        public void ChangeLightLevel(QualityEnum quality)
        {
            
        }

        public void ChangeShadowLevel(QualityEnum quality)
        {
            if(!shadowQualityAdjust) return;
            CameraQualitySetting qualitySetting = GetQualitySetting(quality);
            if (qualitySetting != null && _additionalCamera !=null)
            {
                qualitySetting.ApplyShadowQuality(_additionalCamera);
            }
            
        }

        public void ChangeCameraFrustum(float farDistance,float fov)
        {
            if(!cameraFrustumAdjust) return;

            if (_drivenCamera!=null)
            {
                foreach (var childCamera in _drivenCamera.ChildCameras)
                {
                    CinemachineVirtualCamera child = childCamera as CinemachineVirtualCamera;
                    if (child)
                    {
                        child.m_Lens.FarClipPlane = farDistance;
                        child.m_Lens.FieldOfView = fov;
                    }
                }
            }
            else
            {
                _camera.farClipPlane = farDistance;
                _camera.fieldOfView = fov;
            }
            
        }
        
        public void ChangeAntialiasingMode(AntialiasingMode antialiasingMode)
        {
            if (_camera == null) _camera = GetComponent<Camera>();
            if (_additionalCamera == null) _additionalCamera = GetComponent<UniversalAdditionalCameraData>();
            if (_additionalCamera.renderPostProcessing)
            {
                _additionalCamera.antialiasing = antialiasingMode;
            }
        }
        
        public void ChangeShadowQuality(int shadowDistance, ShadowResolution shadowResolution)
        {
            if (_camera == null) _camera = GetComponent<Camera>();
            if (_additionalCamera == null) _additionalCamera = GetComponent<UniversalAdditionalCameraData>();
            if (_additionalCamera.renderShadows)
            {
                _additionalCamera.m_ShadowDistance = shadowDistance;
                _additionalCamera.m_mainLightShadowmapResolution = shadowResolution;
            }
        }
        
#if UNITY_EDITOR
        private void OnDestroy()
        {
            if (QualityManager.Inst)
            {
                QualityManager.Inst.RemoveQualityListener(this);
            }
        }

#endif
    }
}